package com.xhwl.centiotdata.suppliersystem.haikang;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xhwl.centiotdata.pojo.constant.HaiKangConstant;
import com.xhwl.centiotdata.pojo.dto.haikang.PedestrianRecordHaiKangDTO;
import com.xhwl.centiotdata.pojo.dto.pedestrian.PedestrianIntegrationConfigDTO;
import com.xhwl.centiotdata.utils.ThreadPoolUtils;
import com.xhwl.common.dto.cent.device.DeviceDTO;
import com.xhwl.common.dto.cent.pedes.AuthDTO;
import com.xhwl.common.enums.pedestrian.DoorActionEnum;
import com.xhwl.common.utils.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author： lianghz
 * @Description：
 * @Date 2021/09/03/ 09:44
 */
@Service
public class PedestrianHaiKangHandler {
    private static final Logger log = LoggerFactory.getLogger(PedestrianHaiKangHandler.class);

    private final static String TOPIC_NAME = "pedestrian_snap_user";

    @Autowired
    private KafkaTemplate<String, Object> kafkaTemplate;

    @Autowired
    private GeneralHaiKangHandler generalHaiKangHandler;

    private ReentrantLock lock = new ReentrantLock();

    // 拉取人行记录
    public List<PedestrianRecordHaiKangDTO> pullRecord(PedestrianIntegrationConfigDTO configDTO, Date date) {
        List<PedestrianRecordHaiKangDTO> recordHaiKangDTOList = new ArrayList<>();
        Integer pageNum = 1;
        List<PedestrianRecordHaiKangDTO> recordList = null;
        do {
            recordList = this.requestRecord(pageNum, configDTO, date);
            if (CollectionUtils.isEmpty(recordList)) {
                break;
            }
            // 将出入记录封装成topic，发送给消费者
            kafkaTemplate.send(TOPIC_NAME, "pedestrian_snap_user", JSONObject.toJSONString(recordList));
            recordHaiKangDTOList.addAll(recordList);
            ++pageNum;
        } while (!CollectionUtils.isEmpty(recordList) && recordList.size() == 500);
        return recordHaiKangDTOList;
    }

    private List<PedestrianRecordHaiKangDTO> requestRecord(Integer pageNum, PedestrianIntegrationConfigDTO configDTO, Date date) {
        Map<String, Object> params = new HashMap<>(5);
        params.put("pageNo", pageNum);
        params.put("pageSize", 500);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
        String endTime = sdf.format(date);
        //同步时间范围调整大一些，时间差问题
        Date endDate = new DateTime(date).minusSeconds(40).toDate();
        String startTime = sdf.format(endDate);

        params.put("startTime", startTime);
        params.put("endTime", endTime);
        params.put("eventTypes", HaiKangConstant.DOOR_EVENT_LIST);
//        params.put("doorRegionIndexCode", configDTO.getOrgIndexCode());
        log.error("request params:" + JSONObject.toJSONString(params));
        JSONObject dataObject = this.post(HaiKangConstant.DOOR_EVENTS_URL, params, configDTO);
        JSONArray list = dataObject.getJSONArray("list");

        log.info("海康查询到的数据:{}",JSONObject.toJSONString(dataObject));
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.toJavaList(PedestrianRecordHaiKangDTO.class);
    }


    /**
     * 授权新增
     */
    public void addAuth(PedestrianIntegrationConfigDTO configDTO, AuthDTO authDTO, Integer downloadType) {
        log.info("-----------开始人脸授权-----------");

        if (CollectionUtils.isEmpty(authDTO.getUserOpenIdList()) || CollectionUtils.isEmpty(authDTO.getDeviceOpenIdList())) {
            log.info("人员或者设备信息为空");
            return;
        }

        List<Map<String, Object>> personDatasMapList = new ArrayList<>();
        Map<String, Object> personDatasMap = new HashMap<>(2);
        personDatasMap.put("indexCodes", authDTO.getUserOpenIdList());
        personDatasMap.put("personDataType", "person");
        personDatasMapList.add(personDatasMap);

        List<Map<String, Object>> resourceInfosMapList = new ArrayList<>();
        authDTO.getDeviceOpenIdList().forEach(deviceOpenId -> {
            Map<String, Object> resourceInfosMap = new HashMap<>(2);
            resourceInfosMap.put("resourceIndexCode", deviceOpenId);
            resourceInfosMap.put("resourceType", "door");
            resourceInfosMapList.add(resourceInfosMap);
        });

        Map<String, Object> params = new HashMap<>(4);
        params.put("personDatas", personDatasMapList);
        params.put("resourceInfos", resourceInfosMapList);
        if (null != authDTO.getStartTime()) {
            params.put("startTime", (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")).format(authDTO.getStartTime()));
        }
        if (null != authDTO.getEndTime()) {
            params.put("endTime", (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")).format(authDTO.getEndTime()));
        }
        //权限下载确认
        Map<String, Object> downloadParams = new HashMap<>(2);
        downloadParams.put("resourceInfos", resourceInfosMapList);
        downloadParams.put("taskType", downloadType);

        //添加权限
        this.post(HaiKangConstant.AUTH_ADD_URL, params, configDTO);
        //加锁限制下载进度
        ThreadPoolUtils.pedestrianExecutor.execute(() -> lockProgress(configDTO, downloadParams));
    }

    /**
     * 授权删除
     */
    public void deleteAuth(PedestrianIntegrationConfigDTO configDTO, AuthDTO authDTO, Integer downloadType) {
        log.info("-----------开始删除人脸授权-----------");
        List<Map<String, Object>> personDatasMapList = new ArrayList<>();
        Map<String, Object> personDatasMap = new HashMap<>(2);
        personDatasMap.put("indexCodes", authDTO.getUserOpenIdList());
        personDatasMap.put("personDataType", "person");
        personDatasMapList.add(personDatasMap);
        Map<String, Object> params = new HashMap<>(2);
        params.put("personDatas", personDatasMapList);
        List<Map<String, Object>> resourceInfosMapList = new ArrayList<>();
        Map<String, Object> downloadParams = new HashMap<>(2);
        if (!CollectionUtils.isEmpty(authDTO.getDeletedDeviceOpenIdList())) {
            authDTO.getDeletedDeviceOpenIdList().forEach(deviceOpenId -> {
                Map<String, Object> resourceInfosMap = new HashMap<>(2);
                resourceInfosMap.put("resourceIndexCode", deviceOpenId);
                resourceInfosMap.put("resourceType", "door");
                resourceInfosMapList.add(resourceInfosMap);
            });
            params.put("resourceInfos", resourceInfosMapList);
            downloadParams.put("resourceInfos", resourceInfosMapList);
            this.post(HaiKangConstant.AUTH_DELETE_URL, params, configDTO);
        }
        //下载权限
        //权限下载确认
        downloadParams.put("personDatas", personDatasMapList);
        downloadParams.put("taskType", downloadType);

        //加锁限制下载进度
        ThreadPoolUtils.pedestrianExecutor.execute(() -> lockProgress(configDTO, downloadParams));
    }

    private void lockProgress(PedestrianIntegrationConfigDTO configDTO, Map<String, Object> downloadParams) {
        lock.lock();
        try {
            JSONObject downloadResult = this.post(HaiKangConstant.AUTH_DOWNLOAD_URL, downloadParams, configDTO);
            String taskId = downloadResult.getString("taskId");
            if (StringUtils.isNotEmpty(taskId)) {
                JSONObject obj = new JSONObject();
                obj.put("taskId", taskId);
                while (true) {
                    JSONObject progressResult = this.post(HaiKangConstant.AUTH_DOWNLOAD_QUERY, obj, configDTO);
                    Double totalPercent = progressResult.getDouble("totalPercent");
                    if (totalPercent.compareTo(100d) == 0) {
                        break;
                    }
                    Thread.sleep(1500);
                }
            }
        } catch (Exception e) {
            log.error("权限下载异常", e);
        } finally {
            lock.unlock();
        }
    }

    private JSONObject post(String path, Object params, PedestrianIntegrationConfigDTO configDTO) {
        return generalHaiKangHandler.post(
                path,
                params,
                configDTO.getProjectId(),
                configDTO.getProductId(),
                configDTO.getIpAndPort(),
                configDTO.getAk(),
                configDTO.getSk(),
                configDTO.getTagId());
    }

    public void openDoor(PedestrianIntegrationConfigDTO config, DeviceDTO device, DoorActionEnum action) {
        Map<String, Object> params = new HashMap<>(2);
        params.put("doorIndexCodes", Collections.singletonList(device.getThirdDeviceId()));

        //开门
        int operType = 2;
        boolean doorOpenType = action.getId() == 1;
        if (doorOpenType) {
            operType = 0;
        } else if (action.getId() == 2) {
            operType = 3;
        }
        params.put("controlType", operType);
        post(HaiKangConstant.DOOR_CONTROL_URL, params, config);
    }

    public void addCardAuth(PedestrianIntegrationConfigDTO configDTO, List<String> list, AuthDTO authDTO) {

        Map<String, Object> param = new HashMap<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        param.put("startDate", sdf.format(Objects.isNull(authDTO.getStartTime()) ? new Date() : authDTO.getStartTime()));
        param.put("endDate", sdf.format(authDTO.getEndTime()));

        List<Map<String, Object>> cardList = new ArrayList<>();

        if (CollectionUtils.isEmpty(authDTO.getUserOpenIdList())) {
            return;
        }
        list.forEach(cardNum -> {
            Map<String, Object> cardInfo = new HashMap<>();
            cardInfo.put("cardNo", cardNum);
            cardInfo.put("personId", authDTO.getUserOpenIdList().get(0));
//            cardInfo.put("orgIndexCode", configDTO.getOrgIndexCode());
            cardInfo.put("cardType", 1);
            cardList.add(cardInfo);
        });
        param.put("cardList", cardList);
        this.post(HaiKangConstant.CARD_BINDING_URL, param, configDTO);
    }

    public void deleteCardAuth(PedestrianIntegrationConfigDTO configDTO, List<String> list, AuthDTO authDTO) {
        list.forEach(cardNum -> {
            Map<String, Object> param = new HashMap<>();
            param.put("personId", authDTO.getUserOpenId());
            param.put("cardNumber", cardNum);
            this.post(HaiKangConstant.CARD_DELETION_URL, param, configDTO);
        });
        this.deleteAuth(configDTO, authDTO, 1);
    }
}
